#include <iostream>
#include <cerrno> // C++包C语言头文件常用的方法,和.h效果一样
#include <cstring>
#include <cassert>
#include <unistd.h> // pipe + close + read + write
#include <sys/types.h> // waitpid两个头文件
#include <sys/wait.h>

using namespace std;

int main()
{
    int pipefd[2];
    int ret = pipe(pipefd); // 一.创建管道
    if(ret < 0)
    {
        cerr << errno << ": " << strerror(errno) << endl;
    }
    // cout << "pipefd[0]: " << pipefd[0] << endl; // 3
    // cout << "pipefd[1]: " << pipefd[1] << endl; // 4

    pid_t id = fork(); // 二.创建子进程
    assert(id != -1);
    if (id == 0) // 子进程，读，关闭写
    {
        close(pipefd[1]);
        // 三. 子进程读
        char buffer[1024 * 8];
        while (true)
        {
            // sleep(10);
            ssize_t s = read(pipefd[0], buffer, sizeof(buffer) - 1); // read读
            if (s > 0) // 写入的一方，fd没有关闭，如果有数据，就读，没有数据就等
            {
                buffer[s] = 0;
                cout << "child get a message[" << getpid() << "] Father# " << buffer << endl;
            }
            else if (s == 0) // 写入的一方，fd关闭, 读取的一方，read会返回0，表示读到了文件的结尾
            {
                cout << "writer quit(father), me quit" << endl;
                break;
            }
        }
        close(pipefd[0]);
        exit(0);
    }

    close(pipefd[0]); // 父进程，写，关闭读
    // 四. 父进程写
    string message = "我是父进程，我正 在给你发消息";
    int count = 0;
    char send_buffer[1024 * 8];
    while (true)
    {
        //构建一个变化的字符串
        snprintf(send_buffer, sizeof(send_buffer), "%s[%d] : %d",message.c_str(), getpid(), count++);
        write(pipefd[1], send_buffer, strlen(send_buffer)); // 写入
        sleep(1);
        cout << count << endl;
        if (count == 5) 
        {
            cout << "writer quit(father)" << endl;
            break;
        }
    }
    close(pipefd[1]);
    pid_t ret_id = waitpid(id, nullptr, 0);
    cout << "id : " << id << " ret_id: " << ret << endl;
    assert(ret_id > 0); // 断言只在debug起效
    (void)ret_id; // 只是证明ret_id被使用过

    return 0;
}